package com.javaxiaobang.pachong.csdn.proxy;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

/**
 * Created by xiaobang on 2020/5/29.
 */
@Slf4j
@Component
public class CsdnPaChongConfig {

    //本地博客地址文本中的文章数量
    private int blogUrlSize = 0;
    //本地博客地址文本装入HashMap中
    private HashMap<Integer, String> localBlogUrlMap = null;
    //本地博客地址访问统计
    private HashMap<Integer, Integer> LocalBlogUrlCount = null;
    //访问总量统计
    private int count = 0;
    private HashMap<Integer, String> agentMap = new HashMap<Integer, String>();

    @PostConstruct
    public void getAgentMap() {
        agentMap.put(1, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36");
        agentMap.put(2, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36");
        agentMap.put(3, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36");
    }

    @Autowired
    private PaChongUrl paChongUrl;

    @Async
    public void init() {
        try {
            while (true) {
                sleep(randomClick());
                log.info("开始新的一轮刷新ip");
                log.info(paChongUrl.getProxyUrl());
                localBlogUrlMap = getLocalBlogUrlMap();
                blogUrlSize = localBlogUrlMap.size();
                List<ProxyIp> ipList = getIp(paChongUrl.getProxyUrl());
                LocalBlogUrlCount = initLocalBlogUrlCount();
                for (ProxyIp proxyIp : ipList) {
                    System.setProperty("http.maxRedirects", "50");
                    System.getProperties().setProperty("proxySet", "true");
                    System.getProperties().setProperty("http.proxyHost", proxyIp.getAddress());
                    System.getProperties().setProperty("http.proxyPort", proxyIp.getPort());
                    int id = randomBlogUrl();
                    try {
                        if (LocalBlogUrlCount.get(id) >= 1) {
                            id = randomBlogUrl();
                        }
                        Document doc = Jsoup.connect(localBlogUrlMap.get(id))
                                .userAgent("Mozilla")
//                                .cookie("auth", "token")
                                .timeout(1000)
                                .get();
                        if (doc != null) {
                            count++;
                            LocalBlogUrlCount.put(id, LocalBlogUrlCount.get(id) + 1);
                        }

                        sleepMs(randomClick());
                    } catch (Exception ee) {
                        log.warn(proxyIp.getAddress() + ":" + proxyIp.getPort() + "代理ip不可用");
                    }
                }
                log.info("本轮刷新次数:{}", count);
                show();
            }
        } catch (Exception e) {
            log.info("本轮刷新次数:{}", count, e);
        }
    }

    //访问文章的随机函数，用来模拟真实的访问量操作，以免所有的文章访问量都是一样的，很明显是刷的，此操作随机访问文章，制造访问假象
    public int randomBlogUrl() {
        if (blogUrlSize <= 0) {
            blogUrlSize = 1;
        }
        int id = new Random().nextInt(blogUrlSize);
        return id;
    }

    //获取在【大象代理】中购买的IP，装入ArrayList<ProxyIp>中
    public List<ProxyIp> getIp(String url) {
        List<ProxyIp> ipList = new ArrayList<ProxyIp>();
        try {
            if (System.getProperty("http.maxRedirects") != null) {
                System.clearProperty("http.maxRedirects");
                System.getProperties().remove("proxySet");
                System.getProperties().remove("http.proxyHost");
                System.getProperties().remove("http.proxyPort");
            }

            //1.向ip代理地址发起get请求，拿到代理的ip
            Document doc = Jsoup.connect(url)
//                    .userAgent(getAgent())
//                    .cookie("auth", "token")
                    .timeout(5000)
                    .get();

            //2,将得到的ip地址解析除字符串
            String ipStr = doc.body().text().trim().toString();
            log.info("代理ip:{}", ipStr);

            //3.用正则表达式去切割所有的ip
            String[] ips = ipStr.split("\\s+");


            //4.循环遍历得到的ip字符串，封装成MyIp的bean
            for (final String ip : ips) {
                ProxyIp proxyIp = new ProxyIp();
                String[] temp = ip.split(":");
                proxyIp.setAddress(temp[0].trim());
                proxyIp.setPort(temp[1].trim());
                ipList.add(proxyIp);
            }
        } catch (Exception e) {
            log.warn("获取代理列表出错:", e);
        }
        return ipList;
    }

    public String getAgent() {
        String liulanqi = "Chrome";
        int num = (new Random().nextInt(3));
        liulanqi = agentMap.get(num);
        if (StringUtils.isBlank(liulanqi)) {
            liulanqi = "Mozilla";
        }
        return liulanqi;
    }

    public HashMap<Integer, String> getLocalBlogUrlMap() {
        HashMap<Integer, String> map = new HashMap<Integer, String>();
        try {
            for (int i = 0; i < paChongUrl.getUrlList().size(); i++) {
                map.put(i, paChongUrl.getUrlList().get(i));
            }
        } catch (Exception e) {
            log.warn("获取博客地址出错:", e);
        }
        return map;
    }

    //时间的随机函数，用来模拟真实的访问量操作，以防被博客后台识别，模拟操作60-200秒内的随机秒数,
    public int randomClick() {
        int time = (new Random().nextInt(10));
        return time;
    }

    //休眠进程，单位是分钟,CSDN的规则好像是：每个IP访问一个博客地址的时间间隔是5-15分钟，计数一次
    public void sleepMs(int s) throws InterruptedException {
        long ms = s * 50;
        Thread.sleep(ms);
    }

    //休眠进程，单位是分钟,CSDN的规则好像是：每个IP访问一个博客地址的时间间隔是5-15分钟，计数一次
    public void sleep(int s) throws InterruptedException {
        log.info("睡眠{}秒", s);
        long ms = s * 1000;
        Thread.sleep(ms);
    }


    //访问统计
    public HashMap<Integer, Integer> initLocalBlogUrlCount() {
        HashMap<Integer, Integer> temp = new HashMap<Integer, Integer>();
        for (int i = 0; i < blogUrlSize; i++) {
            temp.put(i, 0);
        }
        return temp;
    }

    //展示访问统计总量
    public void show() {
        log.info("访问量统计：");
        for (int i = 0; i < LocalBlogUrlCount.size(); i++) {
            log.info("博客【" + localBlogUrlMap.get(i) + "】:" + LocalBlogUrlCount.get(i) + "次\t");
        }
        log.info("总计：" + count + "次");
    }

}
